<?php
namespace src\logic\workflow;
use classlib\core as C;
use classlib\core\lang;
/**************************************************************
 * 回传给view模板节点对象数据
 * @author leicc@igg.com
 **************************************************************/
class doc_view extends \stdClass {
	public $createtime;
	public $accepttime;
	public $completetime;
	public $assignuser;
	public $acceptusername;
	public $deliverinfo;
	public $acceptuid;
	public $ccreceivers;
	public $ccsender;
	public $remark;
	public $result;

	/**
	 * 节点视图信息构造函数
	 * @param array $state
	 */
	public function __construct($state, $userid) {
		if ($state['json']) { //将Json请求的数据对象附加到视图属性中
			$json = json_decode($state['json'], true);
			foreach ($json as $key=>$val) {
				$this->$key = $val;
			}
		}
		$this->createtime    = doc_executor::datetime($state['createtime'], true);
		$this->accepttime    = doc_executor::datetime($state['accepttime']);
		$this->completetime  = doc_executor::datetime($state['completetime']);
		$this->assignuser    = $state['assignuser'];
		$this->acceptusername= $state['acceptusername'];
		$this->deliverinfo   = $state['deliverinfo'];
		$this->result        = $state['result'];
		$this->ccreceivers   = $state['ccreceivers'];
		$this->ccsender      = $state['ccsender'];
		$this->remark        = $state['remark'];
		$this->acceptuid     = $state['acceptuid'];
		if (!$this->acceptusername) {
			$this->acceptusername = doc_executor::disname($userid);
		}
		//任务指派的接收者
		if (is_numeric($this->acceptuid)) {
			$this->acceptuid = ($this->acceptuid < 1)? '':doc_executor::disname($this->acceptuid);
		}
	}
};

/**************************************************************
 * 回传给view模板节点对象数据
 * @author leicc@igg.com
 **************************************************************/
class doc_node {
	public $nodeid;
	public $stateid;
	public $name;
	public $tips;
	public $panel;
	public $button;
	public $dosubmit;
	public $data;

	/**
	 * 结点资料信息构造函数
	 * @param int $nodeid
	 * @param string $name
	 * @param string $panel
	 * @param string $button
	 */
	public function __construct($nodeid, $name, $panel, $button, $stateid=0) {
		$this->nodeid 	= $nodeid;
		$this->name   	= $name;
		$this->panel  	= $panel;
		$this->button 	= $button;
		$this->stateid  = $stateid;
		$this->dosubmit = 0;
	}
};
/*****************************************************************
 * 执行实例业务的分解 数据的整合
 * @author Administrator
 *****************************************************************/
class doc_executor {
	//流程状态配置
	const INPROGRESS	= 1;//正在执行
	const NODEHANG  	= 2;//节点挂起中
	const ENDSUB     	= 3;//执行结束
	const PROGRESSHANG 	= 4;//流程已挂起
	const TERMINATE     = 5;//流程已终止
	//结点状态配置
	const WAITACCEPT   	= 0;//待认
	const WAITPROCESS 	= 1;//待办
	const PASSED        = 2;//通过
	const REJECTPASS    = 3;//拒绝通过
	const REJECTCHECK   = 4;//验收不通过
	const CHECKED		= 5;//验收通过
	//执行状态配置
	const EXEC_COMPLETE = 3;
	const EXEC_EXCEPTION= 1;
	const EXEC_SUCCESS  = 2;
	//执行控制角色
	const DEPT_LEADER   = 8;
	const MAIN_LEADER   = 9;
	const APPLY_USER    = 10;
	const ASSIGN_USER   = 19;
	//对于节点属于这几种状态往下继续
	static $nextpass 	= array(2, 5, 6);
	static $nextreject  = array(3, 4);
	
	/**
	 * 单据的状态栏位
	 * @var string
	 */
	public $statusbar;
	
	/**
	 * 执行实例id编号
	 * @var int
	 */
	public $executorid;
	
	/**
	 * 执行实例的状态
	 * @var int
	 */
	public $status;
	
	/**
	 * 工作流程id编号
	 * @var int
	 */
	public $workflowid;
	
	/**
	 * 是否允许停止
	 * @var bool
	 */
	public $isdostop;
	
	/**
	 * 是否允许接收任务
	 * @var bool
	 */
	
	public $isdoaccept;
	/**
	 * 申请者用户id编号
	 * @var int
	 */
	
	public $applyuserid;
	
	/**
	 * 工作流名称 title 标题
	 * @var string
	 */
	public $title;
	
	/**
	 * 应对结点id配置列表
	 * @var Node array
	 */
	public $nodes;
	
	/**
	 * 记录当前处理的结点id编号
	 * @var int
	 */
	public $nodeid;
	
	/**
	 * 当前处理结点id状态
	 * @var int
	 */
	public $stateid;
	
	/**
	 * 任务转单的时候使用
	 * @var int  $stateid
	 */
	public $deliverid;
	
	/**
	 * 当前处理登录的用户id
	 * @var int
	 */
	public $luserid;
	
	/**
	 * 提示语言包配置
	 * @var array
	 */
	private $tlng;
	
	/**
	 * 获取资料信息的执行者信息
	 * @var \src\logic\workflow\doc_basic
	 */
	private $exector;
	
	/**
	 * 构造初始化对象资料信息
	 * @param int $executorid
	 * @param int $workflowid
	 */
	public function __construct($executorid, $workflowid) {
		$this->executorid = $executorid;
		$this->workflowid = $workflowid;
		$this->nodeid     = 0;
		$this->stateid    = 0;
		$this->deliverid  = 0;
		$this->status     = 1;
		$this->isdostop   = false;
		$this->isdoaccept = false;
		$this->nodes      = array();
		$this->tlng       = array();
	}
	
	/**
	 * 初始化构造函数
	 * @throws \Exception
	 */
	public function __init__($ousrid) {
		$lang  = C\lang::inst('adm');
		$norm  = C\model::load('main.proc.node');
		$vorm  = C\model::load('main.proc.nodeform');
		$sorm  = C\model::load('main.proc.nodestate');
		$dlang = lang::inst('dd');
		//初始化大的资料信息
		$this->luserid     = $ousrid;
		$this->applyuserid = $ousrid;
		$this->statusbar   = $lang->get('workflow', '50018');
		if ($this->executorid > 0) {
			$data = C\model::load('main.proc.execution')->get_one($this->executorid);
			if (!$data) {
				throw new \Exception(404, $lang->get('workflow', '50019'));
			}
			$status            = $dlang->get('wk00001', $data['status']);
			$stime             = self::datetime($data['stime']);
			$this->status      = $data['status'];
			$this->workflowid  = $data['workflowid'];
			$this->applyuserid = $data['applyuserid'];
			$statusbar         = $lang->get('workflow', '50020');
			$this->statusbar   = sprintf($statusbar, $status, $data['applyusername'], $stime);
		}
		$data = C\model::load('main.proc.workflow')->get_one($this->workflowid);
		if (empty($data) || $data['status'] != 1) {
			throw new \Exception(404, $lang->get('workflow', '50019'));
		}
		$this->title   = $data['name'];
		$this->exector = new $data['clasz'];
		//判断是否允许终止 只有申请人自己有权限终止
		if ($this->executorid > 0 && $this->status == 1 && $this->applyuserid == $ousrid) {
			$this->isdostop = $this->exector->isstopable($this->executorid);
		}
		//初始化结点表单以及展示的参数信息列表
		$noids= array();
		if ($this->executorid < 1) {
			$where = array('workflowid'=>$this->workflowid, 'preid'=>0);
			$noids = $norm->get_column(0, 1, $where, 'id');
		} else {
			$where = array('executionid'=>$this->executorid);
			$noids = $sorm->get_column(0, -1, $where, 'nodeid', 'id', \classlib\orm::ASC);
		}
		//初始化doc_node资料信息
		$this->tlng= $lang->get('workflow');
		foreach ($noids as $nodeid) {
			$this->nodes[] = $this->__node__($nodeid, $norm, $sorm, $vorm);
		}
	}
	
	/**
	 *
	 * @param int $nodeid
	 * @param \classlib\core\model $norm
	 * @param \classlib\core\model $sorm
	 * @param \classlib\core\model $vorm
	 */
	public function __node__($nodeid, &$norm, &$sorm, &$vorm) {
		$data  = $norm->get_one($nodeid);
		$view  = $vorm->get_one($data['formid']);
		$node  = new doc_node($data['id'], $data['name'], $view['panelobj'], $view['panelbtn']);
		$where = array('executionid'=>$this->executorid, 'nodeid'=>$nodeid);
		$state = $sorm->get_item($where);
		$node->dosubmit = ($state)? 0:1;
		$node->stateid  = ($state)? $state['id']:0;
		//补充结点资料信息的展示
		if ($this->status == 1 && $state['status'] == 1 && $state['acceptuserid'] == $this->luserid) {
			$this->deliverid = $state['id'];
			$this->nodeid    = $nodeid;
			$node->dosubmit  = 1;
		}
		if ($this->status == 1 && $state['status'] == 0 && $data['preid'] != 0) { //判断是否可接受处理任务
			$this->isdoaccept = $this->exector->isaccpetable($this->luserid, $data['roleid'], $state);
			if ($this->isdoaccept) {//接收单据的时候使用
				$this->stateid = $state['id'];
			}
		}
		//处理表单业务个性化数据的自动化填充
		$this->exector->{$data['actions']}($state);
		//填充表单的数据信息项目
		$node->data = new doc_view(empty($state)? $sorm->get_fields():$state, $this->luserid);
		$node->tips = $this->__tips__($data, $state, $node->dosubmit);
		return $node;
	}
	
	/**
	 * 获取表单右侧的提示语展示
	 * @param array $node
	 * @param array $state
	 * @return string
	 */
	public function __tips__($node, $state, $issubmit=false) {
		$tips   = array();
		$dlang  = lang::inst('dd');
		$wlang  = $this->tlng;
		$gorm   = C\model::load('main.sys.role');
		$role   = $gorm->get_one($node['roleid']);
		$status = empty($state)? 1:$state['status'];
		$tips[] = '<span class="wkfl-node icon-default icon">'.$node['name'].'</span><br />';
		$tips[] = '<span class="proc-node '.((in_array($status, self::$nextreject))? 'proc-bad':'proc-good').'">';
		$tips[] = $wlang['50021'].$role['name'].'<br />';
		$tips[] = $wlang['50022'].$dlang->get('wk00002', $status).'<br />';
		if ($state && $state['acceptuid'] > 0) {
			$tips[] = $wlang['50023'].self::disname($state['acceptuid']).'<br />';
		}
		$tips[] = sprintf($wlang['50024'], $node['expire']/24.00).'<br />';
		//接受处理节点的用户
		if($state && $state['acceptuserid'] > 0) {
			$tips[]     = $wlang['50025'].$state['acceptusername'].'<br />';
			if (!empty($state['deliverinfo'])) {
				$tips[] = $wlang['50026'].$state['deliverinfo'].'<br />';
			}
			$tips[]     = $wlang['50027'].self::datetime($state['accepttime']).'<br />';
			$tips[]     = $wlang['50028'].self::datetime($state['completetime']).'<br />';
			if ($state['status'] != 1) {
				$ltime  = $state['expire'] - (($state['completetime'] > 0)? $state['completetime']:C\config::$nowtime);
				$ltime  = ($ltime < 0)? '0.00':sprintf('%.2f', $ltime / 86400.00);
				$tips[] = sprintf($wlang['50029'], $ltime).'<br />';
			}
		}
		$tips[] = '</span>';
		if ($issubmit == 1) {
			$tips[] = '<a name="NN">&nbsp;</a>';
		}
		return implode('', $tips);
	}
	
	/**
	 * 格式化输出时间
	 * @param int $stime
	 * @return string
	 */
	public static function datetime($stime, $isnow=false) {
		if ($stime > 0) {
			return date('Y-m-d H:i:s', $stime);
		}
		return (!$isnow)? '':date('Y-m-d H:i:s');
	}
	
	/**
	 * 获取格式化的昵称资料信息
	 * @param int $userid
	 * @return string
	 */
	public static function disname($userid) {
		$user = C\model::load('main.sys.user')->get_one($userid);
		$name = $user['nickname'].'['.$user['account'].']';
		return $name;
	}
}